<script setup lang="ts">
defineOptions({ name: 'BaseBob' })
const props = withDefaults(defineProps<Props>(), {
  header: 'header',
  showCycle: true,
  needMove: false,
  isSearch: false,
  filterFn: (i: Option, v: string) => i.label.includes(v),
})
const emits = defineEmits(['update:show', 'update:selected'])
interface Option {
  label: string
  desc?: string
  value: any
}
interface Props {
  show: boolean
  header?: string
  selected?: string | number
  option?: Array<Option> | (() => Array<Option>)
  showCycle?: boolean
  needMove?: boolean
  isSearch?: boolean
  filterFn?: (i: Option, v: string) => boolean
}
const filterVal = ref('')
const options = computed(() => {
  const opts = props.option
  return typeof opts === 'function' ? opts() : opts || []
})
const list = computed(() => {
  return options.value?.filter(item => props.filterFn(item, filterVal.value))
})

function onClose() {
  emits('update:show', false)
}
function onClick(v: any) {
  emits('update:selected', v)
  emits('update:show', false)
}
function moveToCenter() {
  const selectedEl = document.querySelector('.selected-item') as HTMLElement
  const scrollCon = document.querySelector('.bob-content')
  const container = document.querySelector('.bob-wrapper-container')
  if (scrollCon && container) {
    const height = Math.round(container.getBoundingClientRect().height)
    const targetPosition = selectedEl.offsetTop - Math.round(height / 2)
    scrollCon.scrollTo({
      top: targetPosition,
      behavior: 'smooth',
    })
  }
}
watch(
  () => props.show,
  (val) => {
    if (val) {
      document.body.style.overflow = 'hidden'
      if (props.needMove) {
        nextTick(() => {
          moveToCenter()
        })
      }
    }
    else {
      filterVal.value = ''
      document.body.style.overflow = ''
    }
  },
)
</script>

<template>
  <Transition name="bob-animal">
    <div v-show="show" class="size-full fixed z-200 top-0 left-0 bob-wrapper" @click="onClose">
      <Transition name="bob-container">
        <div
          v-if="show"
          class="fixed w-full bottom-0 min-h-20 max-h-[80%] pt-[3.5rem] bob-wrapper-container flex flex-col rounded-t-xl"
          @click.stop
        >
          <div class="bob-title text-base">
            {{ header }}
            <BaseButton type="none" class="bob-close !p-0" @click="onClose">
              <BaseIcon name="uni-close2" class="text-xl scale-50" />
            </BaseButton>
          </div>
          <div class="scroll-y bob-content" style="overscroll-behavior-y: contain">
            <slot>
              <div class="scroll-container">
                <div>
                  <div v-if="isSearch" class="bob-input w-full sticky -top-2 z-30 -mt-2 py-3">
                    <BaseInput search name="searchVal" @update:model-value="(v) => filterVal = v" />
                  </div>
                  <BaseButton v-for="cur in list" :key="cur.value" class="text-sm font-semibold w-full text-white item" :class="[showCycle ? 'radio' : 'justify-normal', { 'selected-item': cur.value === selected }]" type="none" :aria-selected="cur.value === selected" @click="onClick(cur.value)">
                    <slot v-if="cur.label" name="label" :label="cur.label">
                      <span class="min-w-12 mr-1 text-left font-semibold">{{ cur.label }}</span>
                    </slot>
                    <span v-if="cur.desc" class="text-ellipsis max-w-60 text-xs">{{ cur.desc }}</span>
                  </BaseButton>
                </div>
              </div>
            </slot>
          </div>
        </div>
      </Transition>
    </div>
  </Transition>
</template>

<style>
:root{
  --bc-base-bob-input-bg: #232626;
  --bc-base-bob-label-desc-font-size: 0.75rem;
}
</style>

<style scoped lang="scss">
.bob-animal-enter-active,
.bob-animal-leave-active {
  transition: background-color 0.2s ease
}

.bob-animal-enter-from,
.bob-animal-leave-to {
  background-color: rgba(16,18,18,0);
}

.bob-animal-enter-to,
.bob-animal-leave-from {
  background-color: rgba(16,18,18,0.8);
}

.bob-container-enter-active,
.bob-container-leave-active {
  transition: transform 0.2s ease
}

.bob-container-enter-from,
.bob-container-leave-to {
  transform: translateY(100%);
}

.bob-container-enter-to,
.bob-container-leave-from {
  transform: translateY(0);
}
.bob-wrapper{
  background-color: rgba(16,18,18,0.8);
  &-container{
    background-color: rgb(35,38,38);
  }
}
  .bob-title {
    position: absolute;
    top: 0;
    width: 100%;
    justify-content: center;
    align-items: center;
    font-weight: 600;
    height: 3rem;
    font-size: 0.875rem;
    display: flex;
    flex: none;
    color: white;
  }
  .bob-close {
    position: absolute;
    right: 0.875rem;
    top: 0.625rem;
    border-radius: 0.375rem;
    width: 1.75rem;
    height: 1.75rem;
    background-color: #464f50;
  }
  .bob-content {
    padding: 0 1rem 1rem;
  }
  .bob-input{
    background-color: var(--bc-base-bob-input-bg);
  }
  .item {
    width: 100%;
    border-radius: .5rem;
    padding: 0 0.5rem 0 0.75rem;
    user-select: none;
    touch-action: manipulation;
    font-size: var(--bc-base-bob-label-desc-font-size);
  }
  .selected-item{
    background-color: rgb(50, 55, 56);
  }
  .scroll-container {
    display: flex;
    flex-direction: column;
    min-height: auto;
  }
  .radio {
    display: flex;
    height: 2.5rem;
    flex: none;
    align-items: center;
  }
  .radio::before {
    content: "";
    display: block;
    flex: none;
    transition-duration: .15s;
    transition-property:all;
    border-radius: 100rem;
    width: 1.375rem;
    height: 1.375rem;
    border: 0.125rem solid #e4eaf019;
    order: 100;
    margin-left: auto;
    margin-right: 0;
}
.radio[aria-selected=true]::before {
    border-width: 0.375rem;
    border-color: rgb(36 238 137);
}
</style>
